package cn.fuxi2022.core.exception;

import cn.fuxi2022.core.utils.ExceptionUtil;
import cn.fuxi2022.model.resp.R;
import lombok.extern.slf4j.Slf4j;
import org.springframework.validation.BindException;
import org.springframework.validation.BindingResult;
import org.springframework.validation.ObjectError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;

import java.util.List;

/**
 * 全局统一异常处理
 *
 * @author fuxi
 */
@RestControllerAdvice
@Slf4j
public class SmartGroupExceptionHandler {


    @ExceptionHandler(Exception.class)
    public R systemException(Exception exception) {
        exception.printStackTrace();

        String message = "系统错误，请联系管理员";
        if (exception instanceof BindException) {
            // 如果当前异常是由表单校验的绑定异常引发的，就返回校验的错误
            //获取并拼接所有错误信息
            BindException bindException = (BindException) exception;
            BindingResult bindingResult = bindException.getBindingResult();

            message = subValidationMessage(bindingResult);
            return R.error(message);

        } else if (exception instanceof MethodArgumentNotValidException) {
            // 如果当前异常是由表单校验的方法参数无效异常引发的，就返回校验的错误
            MethodArgumentNotValidException methodArgumentNotValidException = (MethodArgumentNotValidException) exception;
            BindingResult bindingResult = methodArgumentNotValidException.getBindingResult();

            message = subValidationMessage(bindingResult);
            return R.error(message);
        }
        // 将日志堆栈信息输出到文件
        log.error(ExceptionUtil.getMessage(exception));
        return R.error(message).put("message", exception.getMessage());
    }

    @ExceptionHandler(SmartGroupException.class)
    public R GroupException(Exception exception) {
        exception.printStackTrace();
        return R.error(exception.getMessage());
    }

    /**
     * 截取 Validation 异常信息，作为结果返回
     *
     * @param bindingResult Validation的BindingResult（绑定接口通用接口）
     * @return 异常信息
     */
    private String subValidationMessage(BindingResult bindingResult) {

        //使用StringBuilder来拼接错误信息,减少对象开销
        StringBuilder stringBuilder = new StringBuilder();

        List<ObjectError> allErrors = bindingResult.getAllErrors();
        for (ObjectError item : allErrors) {
            stringBuilder.append(item.getDefaultMessage())
                    .append(',');
        }
        //删除最后一个逗号
        stringBuilder.deleteCharAt(stringBuilder.length() - 1);

        return stringBuilder.toString();
    }

}
